#pragma once

#include <grpcpp/grpcpp.h>
#include "const.h"
#include "proto/message.grpc.pb.h"
#include <atomic>
class ChatConPool 
{
public:
	ChatConPool(size_t poolsize, std::string host, std::string port) :_poolsize(poolsize), _host(host), _port(port), b_stop(false) 
	{
		for (size_t i = 0;i < poolsize;++i)
		{
			std::shared_ptr<grpc::Channel> channnel = grpc::CreateChannel(host + ":" + port, grpc::InsecureChannelCredentials());
			_connections.push(message::ChatService::NewStub(channnel));
		}
	}

	~ChatConPool() 
	{
		std::lock_guard<std::mutex> lock(_mutex);
		Close();
		while (!_connections.empty()) {
			_connections.pop();
		}
	}

	std::unique_ptr<message::ChatService::Stub> GetConnection() {
		std::unique_lock<std::mutex> lock(_mutex);
		_cond.wait(lock, [this] {
			if (b_stop) {
				return true;
			}
			return !_connections.empty();
			});

		if (b_stop) {
			return nullptr;
		}

		auto context = std::move(_connections.front());
		_connections.pop();
		return context;
	}

	void ReturnConnection(std::unique_ptr<message::ChatService::Stub> con) {
		std::lock_guard<std::mutex> lock(_mutex);
		if (b_stop) {
			return;
		}
		_connections.push(std::move(con));
		_cond.notify_one();
	}

	void Close() 
	{
		b_stop = true;
		_cond.notify_all();
	}

private:
	std::atomic<bool> b_stop;
	size_t _poolsize;
	std::string _host;
	std::string _port;
	std::queue<std::unique_ptr<message::ChatService::Stub> >_connections;
	std::mutex _mutex;
	std::condition_variable _cond;
};
class ChatGrpcClient
{
public:
	static ChatGrpcClient& GetInst();
	~ChatGrpcClient() {
	}
	message::AddFriendRsp NotifyAddFriend(std::string server_ip, const message::AddFriendReq& req);
	message::AuthFriendRsp NotifyAuthFriend(std::string server_ip, const message::AuthFriendReq& req);
	bool GetBaseInfo(std::string base_key, int uid, std::shared_ptr<UserInfo>& userinfo);
	message::TextChatMsgRsp NotifyTextChatMsg(std::string server_ip, const message::TextChatMsgReq& req, const Json::Value& rtvalue);
private:
	ChatGrpcClient();
	std::unordered_map<std::string, std::unique_ptr<ChatConPool>> _pool;

};

